iT邦幫忙

2023 iThome 鐵人賽

DAY 19
0

今天沒有歌曲靈感,只好歌名來湊XD
不過應該昨天點播這首才符合主題/images/emoticon/emoticon15.gif

Yes

因為多對多關聯的複雜度高,常被視為資料庫設計中的一大挑戰。
當兩個實體間存在多對多關係,要如何有效地表達、以及如何保持其資料的完整性和一致性,都是值得深入探討的議題。今天 Day 19 要來探討背後的設計理念,並透過程式碼範例,解釋如何在 Spring Data JPA 中實現多對多關係~

一、多對多關聯是什麼?

在用 database 說明多對多前,先用一個簡單的例子來說明。回到過去在學時期學校中的學生和課程,一位學生可以選修多門課程,而一門課程也可以被多位學生選修。在這,學生和課程間的關係就是典型的多對多。

二、如何在資料庫中表達多對多關聯?

多對多關聯通常在資料庫中透過一個中介表格(join table, junction table or cross-reference table)來實現。這個表包含了多對多這兩個實體的外鍵。以學生&課程為例,會有一個選課表,裡頭記錄學生和課程的關聯資訊。

學生表(Students)

ID
Name
...
課程表(Courses)
ID
CourseName
...
學生課程關聯表(StudentCourses)

StudentID (FK,指向學生表的ID)
CourseID (FK,指向課程表的ID)

在這個結構中,每位學生的每個課程透過「學生課程關聯表」記錄裡表間的關聯,這樣就可以輕鬆查詢某堂課被哪些學生選修,以及一個學生選修了哪些課程。

三、實際應用:

  1. 電商平台:一個客戶可以購買多種商品,同時一種商品可以被多個客戶購買。
  2. 社群媒體:一個用戶可以加入多個群組,而一個群組也可以有多個用戶。
  3. 框架:在許多現代軟體框架(Software framework)中,如 Django、Rails 或 Hibernate,多對多關聯可以通過高級的 API 來操作和管理,我們不需要直接與中介表互動框架會主動處理大部分細節。

四、在 Spring Data JPA 中實作多對多

我們可以使用 @ManyToMany 註解來表示多對多,同時還需要使用 @JoinTable 註解來指定中介表格的資訊。
但需要特別注意 方向性 問題。多對多關聯可以是單向或雙向。多數情況下雙向關聯較為常見,但這也代表在 更新查詢 資料的時候得更加小心確保資料的一致性。

📌以下是書商平台中的「書籍」和「作者」的舉例:

假設我們在經營一個專賣書的電商平台系統,在系統中每本書可能有多位作者,而每位作者也可能寫了多本書,兩者為多對多關係。

  1. 實體設計
@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;

    @ManyToMany
    @JoinTable(
      name = "book_author",
      joinColumns = @JoinColumn(name = "book_id"),
      inverseJoinColumns = @JoinColumn(name = "author_id"))
    private List<Author> authors = new ArrayList<>();

    // 省略 getters 和 setters
}

@Entity
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @ManyToMany(mappedBy = "authors")
    private List<Book> books = new ArrayList<>();

    // 省略 getters 和 setters
}

  1. 中介表格

這裡的 book_author 就是多對多關聯的中介表。它包含了 book_idauthor_id 兩個 FK。

CREATE TABLE book_author (
    book_id BIGINT,
    author_id BIGINT,
    PRIMARY KEY (book_id, author_id),
    FOREIGN KEY (book_id) REFERENCES Book(id),
    FOREIGN KEY (author_id) REFERENCES Author(id)
);

  1. 如何使用

當我們想要為一本書添加作者時,只需將該作者加入到那本書的 authors 列表中,並保存這本書的實體。

Book book = new Book();
book.setTitle("Spring Boot 實戰");
Author author1 = new Author();
author1.setName("Alice Yang");
Author author2 = new Author();
author2.setName("Bob Chen");
book.getAuthors().add(author1);
book.getAuthors().add(author2);
bookRepository.save(book);

多對多在資料庫設計中是一個不可或缺的部分,但實務上不太建議使用多對多,原因如下:

1. 資料複雜性

  • 資料維護:多對多關係可能導致資料維護上的複雜性,改動不易。
  • 資料重複:有資料重複的風險和一致性問題。

2. 查詢效能

  • 效能問題:在涉及大量資料時,多對多關係可能導致查詢效能下降。

3. 資料庫正規化

雖然多對多關係在某些情境下是必要的,但在實務應用中,通常建議透過中介表來管理和簡化這種複雜關係,來達到更好的效能和資料管理。


上一篇
Day 18:One-to-Many
下一篇
Day 20 - Validation
系列文
Spring Boot 三十天挑戰賽30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言